package game.view;

import game.model.GameModels;
import game.model.Position;

import javax.swing.*;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.util.Iterator;
import java.util.function.BiFunction;
import java.util.function.Consumer;

/**
 * 游戏地图绘制器，遵守观察者模式
 */
class GameMapPanel extends JPanel {
    private final int UNIT; // 单位长，从模型坐标到屏幕坐标


    /**
     * 构造函数
     *
     * @param models 观察对象
     * @param UNIT   单位长
     */
    public GameMapPanel(GameModels models, int UNIT) {
        super();
        this.models = models;
        this.UNIT = UNIT;
        super.setPreferredSize(new Dimension((models.MAP_WIDTH) * UNIT, (models.MAP_HEIGHT) * UNIT));
    }

    private final GameModels models; // 观察对象

    /**
     * 绘制面板的内容。
     * 创建 JPanel 后会自动调用一次该方法。
     * 之后如果需要重新绘制，应调用 updateUI() 方法。
     */
    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g); // 调用基类的绘制方法，以擦除旧的内容
        Graphics2D g2d = (Graphics2D) g.create(); // 创建 Graphics 的副本。防止绘制时改变 Graphics 原有的参数
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); // 抗锯齿
        // 画地图
        g2d.setColor(Color.BLACK); // 设置画笔颜色
        for (int x = 0; x < models.MAP_WIDTH; ++x) {
            for (int y = 0; y < models.MAP_HEIGHT; ++y) {
                Position screenPos = modelToScreen(new Position(x, y));
                g2d.drawRect(screenPos.x, screenPos.y, UNIT, UNIT); // 画格子
            }
        }

        // 画蛇
        Color snakeColor = new Color(255, 0, 0);
        g2d.setColor(snakeColor); // 设置画笔颜色
        Iterator<Position> iterator = models.snake.iterator();
        // 蛇头
        {
            Position head = modelToScreen(iterator.next());
            // 三角形
            int[] xPoints = {head.x, head.x, head.x + UNIT}; // x坐标
            int[] yPoints = {head.y, head.y + UNIT, head.y + UNIT / 2};  // y坐标
            Polygon triangle = new Polygon(xPoints, yPoints, 3); // 多边形
            AffineTransform initialTransform = g2d.getTransform(); // 在绘制之前保存初始的AffineTransform状态
            g2d.rotate(Math.PI / 2 * models.snakeDirection, head.x + UNIT / 2, head.y + UNIT / 2); // 将画布逆时针旋转，坐标系不变
            g2d.fill(triangle);
            g2d.setTransform(initialTransform); // 恢复初始的 AffineTransform 状态，将视角转回
        }
        // 蛇身
        while (iterator.hasNext()) {
            Position position = iterator.next();
            Position screenPos = modelToScreen(position);
            g2d.fillOval(screenPos.x, screenPos.y, UNIT, UNIT); // 画圆
        }
        // 画食物
        Color foodColor = new Color(0, 0, 255);
        g2d.setColor(foodColor); // 设置画笔颜色
        Position foodScreenPos = modelToScreen(models.food);
        g2d.fillOval(foodScreenPos.x, foodScreenPos.y, UNIT, UNIT); // 画圆

        g2d.dispose(); // 自己创建的副本用完要销毁掉
    }

    // util function
    private Position modelToScreen(Position model) {
        return new Position(model.x * UNIT, model.y * UNIT);
    }

}
